/**
 * @author lwlianghehe@gmail.com
 * @date 2024/11/22
 */

import axios from 'axios'
import {getErpPrefix, getFilePrefix} from "./env.ts";
import {goLogin} from "../util/routerUtils.ts";
import { ElNotification } from 'element-plus'

const baseURL = '/'
// const baseURL = 'http://localhost:8090/'
const noNeedToken = ['/login', '/register']

// 扩展axios配置类型
declare module 'axios' {
    interface AxiosRequestConfig {
        customErrorHandler?: boolean;        // 使用自定义错误处理
        skipErrorNotification?: boolean;     // 跳过错误通知
        skipToken?: boolean;                // 跳过token添加
        returnFullResponse?: boolean;       // 返回完整响应而不是data
    }
}

// 拦截器
axios.interceptors.request.use((config) => {
    config.baseURL = baseURL
    
    // 根据配置决定是否添加token
    if (!config.skipToken && config.url && !noNeedToken.includes(config.url, 0)) {
        config.headers.token = localStorage.getItem('token')
    }

    return config  // 必须返回config
}, (error) => {
    return Promise.reject(error)
})

axios.interceptors.response.use((response) => {
    // 如果设置了返回完整响应
    if (response.config.returnFullResponse) {
        return response
    }
    
    if (response.config.responseType == 'blob') {
        return response
    }
    if(response.config.responseType == 'arraybuffer') {
        return response
    }

    return response.data
}, (error) => {
    // 如果设置了自定义错误处理，直接抛出原始错误
    if (error.config?.customErrorHandler) {
        return Promise.reject(error)
    }
    
    // 判断是"网络错误"或"服务器无法连接"
    if (!error.response) {
        // 断网/服务挂了/CORS等
        if (error.code === 'ECONNABORTED') {
            return Promise.reject({code: 400, msg: '请求超时'})
        } else if (error.message && error.message.includes('Network Error')) {
            return Promise.reject({code: 400, msg: '网络错误'})
        } else {
            return Promise.reject({code: 400, msg: '无法连接服务器'})
        }
    } else {
        // 有 response，是接口报错（如 404、500 等）
        console.log('服务器有响应，但报错', error.response.status);
        if (error.response.status === 401) {
            goLogin()
        }
        
        // 根据配置决定是否显示错误通知
        if (error.response.data && !error.config?.skipErrorNotification) {
            ElNotification({
                title: '错误',
                message: error.response.data.msg,
                type: 'error',
            })
        }
        
        return Promise.reject({code: error.code, msg: error.message})
    }
})

export function getHttp(url: string, config: any): Promise<any> {
    return new Promise((resolve, reject) => {
        axios.get(url, config).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

export function postHttp(url: string, params: any): Promise<any> {
    return new Promise((resolve, reject) => {
        axios.post(url, params).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

export function postDownloadFileHttp(url: string, params: any): Promise<any> {
    return new Promise((resolve, reject) => {
        axios.post(getErpPrefix() + url, params, {responseType: 'blob'}).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

export function postDownloadFileFromFileServer(url: string, params: any): Promise<any> {
    return new Promise((resolve, reject) => {
        axios.post(getFilePrefix() + url, params, {responseType: 'blob'}).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

export function postUploadFileHttp(url: string, file: File): Promise<any> {
    const formData = new FormData()
    formData.append('file', file)
    return new Promise((resolve, reject) => {
        axios.post(getErpPrefix() + url, formData, {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
        }).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

// erp 专用前缀接口
export function postErpHttp(url: string, params: any): Promise<any> {
    return postHttp(getErpPrefix() + url, params)
}

export function postErpHttpWithConfig(url: string, params: any, config: any = {}): Promise<any> {
    return postHttpWithConfig(getErpPrefix() + url, params, config)
}

export function getErpHttp(url: string, params: any): Promise<any> {
    return getHttp(getErpPrefix() + url, params)
}

export default axios

// 辅助函数：使用自定义配置的HTTP请求
export function getHttpWithConfig(url: string, config: any = {}): Promise<any> {
    return new Promise((resolve, reject) => {
        axios.get(url, config).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}

export function postHttpWithConfig(url: string, params: any, config: any = {}): Promise<any> {
    return new Promise((resolve, reject) => {
        axios.post(url, params, config).then((res) => {
            resolve(res)
        }).catch((err) => {
            reject(err)
        })
    })
}



// 示例：跳过错误通知的请求
export function postHttpSkipErrorNotification(url: string, params: any, config: any = {}): Promise<any> {
    return postHttpWithConfig(url, params, { ...config, skipErrorNotification: true })
}

// 示例：返回完整响应的请求
export function getHttpFullResponse(url: string, config: any = {}): Promise<any> {
    return getHttpWithConfig(url, { ...config, returnFullResponse: true })
}

// 示例：使用自定义错误处理的请求
export function postHttpCustomErrorHandler(url: string, params: any, config: any = {}): Promise<any> {
    return postHttpWithConfig(url, params, { ...config, customErrorHandler: true })
}

// 示例：跳过token的请求
export function getHttpSkipToken(url: string, config: any = {}): Promise<any> {
    return getHttpWithConfig(url, { ...config, skipToken: true })
}
